home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 4
/
Precision Software Applications Silver Collection Volume 4 (1993).iso
/
stats
/
chadyn.exe
/
YTOOLS.C
< prev
next >
Wrap
Text File
|
1988-12-08
|
20KB
|
765 lines
/******************* (C) 1986,7,8 by JAMES A. YORKE **************************/
/******************************* YTOOLS.C ************************************/
/* This file Ytools.C contains routines that are general tools
that do not require detailed knowledge of
the differential equation or map under investigation
James Yorke */
/* Routines in YTOOLS.c
These are routines that are essentially independent of the map being studied.
beep
ChooseStorageVec(Character) Character == 0 means StorVec is not provided
distance(y0,y1,dimen)
error_check
get_set(output,mapnum)
int mapnum;
FILE *output;
iterate_map
moduloAB(Y,A,B)
MoveVec() depends on level
null() { } dummy
printWhere()
print_text
print_y()
random
ret_erase_line(i) gives i copies of return(plus line feed) + erase_line()
rungekutta
ScanfForCoefs(A,B,pVec)
setequal(J,K,dimen) use store instead of this
start clears a line & sets dim = 0
store(y0,y1,dimen) sets y0 equal to y1
y_init_init */
/* The core(i.e. pic[]) and screen operations are independent */
#include "yinclud.h"
static long IterateCounter = 0;
static double frac =.31415926;/* seed for random() */
/****************************SUBROUTINES********************************/
FILE *printWhere()
{
if(level < PROCESS || prnFlag == OFF) {
return(StOutPut);
} else
return(stdprn);
}
beep()
{ /* beep() beeps */
putchar('\007'); /* hopefully goes to screen */
}
int ChooseStorageVec(Character)
/* This routine takes a character and puts the
address of the corresponding storage vector
in ystore_in; it accepts only the characters
a, b, ...,e, 0, 1, 2, ... NUM_Y -1, which
correspond to storage vectors; if Character
== 0 then it gets the character from the
keyboard; StorChar is also used by
interrupt() */
char Character;
{
int outcome;
if(Character == 0) {
/*beep();*/
if(SCREEN) {
if(level >= PROCESS) {
PRINT
"hit key 0,1,.. < %d OR 'a','b'...'e' indicating which storage vector to use: "
,NUM_Y);
#ifdef X11
StorChar = awaitkey(0);
#else
while((StorChar = keycheck()) == 0);
/* keep trying until a character is entered */
#endif
}
}
if(level == 2) {
if(SCREEN) {
PRINT
"ENTER 0,1,.. < %d OR 'a','b'...'e' THEN <return> \n"
,NUM_Y);
PRINT
"indicating which storage vector to use: \n");
}
#ifdef X11
if(input == StInput
&& sscanf(xwfgets(), "%c", &StorChar) != 1
|| input != StInput &&
fscanf(input, " %c", &StorChar) != 1)
#else
if((SCREEN && abortEnter() == YES) ||
fscanf(input, " %c", &StorChar) != 1)
#endif
return(0);
}
} else {
StorChar = Character;
}
if(SCREEN)
PRINT " \r %c\n", StorChar);
outcome = 0;
if((StorChar >= '0' && StorChar < '0' + NUM_Y)
|| (StorChar >= 'a' && StorChar <= 'e'))
outcome = 1; /* i.e., character is acceptable */
else {
erase_line();
PRINT " %c is Not acceptable\n", StorChar);
}
/* NOW DETERMINE WHICH STORAGE VECTOR IS INVOLVED */
if(StorChar == '0')
ystore_in = y;
else if(StorChar >= '1' && StorChar < '0' + NUM_Y)
ystore_in = y + eqn0 + eqn1 * (StorChar - '1');
/* the zeroth vector is allocated eqn0 space,
the rest eqns */
else if(StorChar == 'a')
ystore_in = ya;
else if(StorChar == 'b')
ystore_in = yb;
else if(StorChar == 'c')
ystore_in = yc;
else if(StorChar == 'd')
ystore_in = yd;
else if(StorChar == 'e')
ystore_in = ye;
return(outcome);
}
#ifdef TESTING /* not defined */
double dabs(doub) /* abs() takes int arguments and returns an int
*/
double doub;
{
if(doub < 0)
doub = -doub;
return(doub);
}
#endif /* TESTING */
/* yp0 and yp1 are pointers; the distance between
* the vectors(with dimen coordinates)
* starting at addresses yp1 and y2 is computed
* and returned.
*/
double distance(yp0, yp1, dimen)
double *yp0,
*yp1;
int dimen;
{
double distsqrd;
int i;
distsqrd = 0;
for(i = 0; i < dimen; i++)
distsqrd = distsqrd + (yp0[i] - yp1[i]) * (yp0[i] - yp1[i]);
return(sqrt(distsqrd));
}
error_check() { /* This routine is a substitute for rungekutta;
it compares results of a dif eq step with
two half size steps... The distance between
them(=square root of the sum of the squares
of the differences of the y[i] values) is
the error. This error is the error for one
step only and must be recomputed many times
to get an overview of the error size along a
trajectory; the final value of y[] is the
result of the two half-sized steps; the
results are printed on the screen if
"printer" > 2 */
double y_step_dist,
distance();
double y_one[EQTNS0],
y_two[EQTNS0];
/* FIRST THE SOLVER IS APPLIED USING THE CURRENT VALUE OF STEP, AFTER SAVING
THE CURRENT y[] VALUE */
/* eqns >= dim but this causes no problems since vectors are initialized */
store(y_one, y, eqn0); /* store vector y[] in vector y_one[], both
having dimension eqns */
(*IterIteratee) (); /* this usually equals *map which may equal
rungekutta */
y_step_dist = distance(y, y_one, eqn0);
/* this distance between y[] and y_one[] will
be used to measure how big the step is in
phase space using all variables including
any Lyapunov vectors that are being used */
store(y_two, y, eqn0); /* store vector y[] after one step in vector
y_two[], both having dimension eqn0 */
store(y, y_one, eqn0); /* store vector y_one[] back in vector y[] */
/* NEXT A TWO ITERATES ARE TAKEN WITH HALF AS BIG A VALUE OF STEP */
step /= 2;
halfstep /= 2;
sixth_step /= 2;
(*IterIteratee) ();
(*IterIteratee) (); /* this usually equals *map which may equal
rungekutta */
step *= 2;
halfstep *= 2;
sixth_step *= 2;
error = distance(y, y_two, eqn0);
if(error > max_error)
max_error = error;
if(printer > 2 || ODEcheck > 1) {
/* ODEcheck is set > 1 by interrupt 'e' but is
decreased below in this routine */
if(num_lyap <= 0)
scr_rowcol(0, 0);
/* move cursor to top left; if num_lyap > 0,
the lyap exponents might be printed on top
the errors if we returned the cursor */
if(y_step_dist > 0)/* checking so we don't divide by zero */
PRINT
"error= %6.6le;error/step= %6.6le; max error so far = %6.6le \r"
,error, error / y_step_dist, max_error);
/* note \r ends line and returns carriage without advancing a line */
}
if(ODEcheck > 1) /* interrupt 'e' increases ODEcheck by 2 so
that this routine will be called once; */
ODEcheck = ODEcheck - 2;
}
get_set(output, mapname)
char *mapname;
FILE * output;
{
if(strcmp(mapname, "all") == 0)
fputs(setup, output);
}
iterate_map() { /* carries out one iterate(possibly running
error check every 5 dots for dif eqn); after
iteration it calls(*modPointer)() to see if
some value should be taken mod something;
this cannot be done by the differential
equation solver; for non differential
equation maps, the variables are usually
calculated modulo whatever directly within
the map; finally routine checks to see if
y[] should be printed out */
int n;
int OneFifthIC,
ICmod5; /* for checking if IC divisible by 5 */
if(num_lyap > 0 && dot >= 0)/* dot = 0 is the case where lyapunov is
initialized */
if(InNewton == 0)/* = 0 if newton is not being called */
lyapunov();
for(n = 0; n < its_per_plot; n++) {
/* permits several iterates per point plotted
*/
if(step == -9999.)
(*IterIteratee) ();
else {
IterateCounter++;
OneFifthIC = IterateCounter / 5;
/* integer arithmetic */
ICmod5 = IterateCounter - 5 * OneFifthIC;
/* ODEcheck == 1 is turned on by 'E' in YINTRPT.C */
if((ODEcheck >= 1) && (ICmod5 == 0))
error_check();
/* Happens if dot is divisible by 5 */
else
(*IterIteratee) ();
(*modPointer) ();
/* this = null() for non differential equations
and for many differential equations */
}
}
}
double moduloAB(Y, A, B) /* returns a value that is Y shifted by a
multiple of B-A; it is shifted so that the
returned value lies between A and B; note A
and B and Y must be "double" reals; if the
operation changes Y, then modFlag is set =
YES = 1; it should be turned off elsewhere;
it is not clear to me what happens when a
negative double is truncated to an integer
so this routine shifts it to be positive
before truncating and then shifts back */
double Y,
A,
B;
{
double scaledY;
int int_part;
double shift;
scaledY = (Y - A) / (B - A);
if(scaledY >= 0 && scaledY < 1)
return(Y);
modFlag = YES; /* this means that some number is being changed
by this routine */
shift = 10.0;
while(shift + scaledY < 0)
shift *= 10.0;
int_part = shift + scaledY;
/* we only take the integer part of a positive
number; */
return(A + (B - A) * (scaledY + shift - int_part));
}
MoveVec() { /* asks for source vector and then the target
vector, each designated by one character;
then the target is set equal to the value in
the source. */
char Sto;
int acceptable;
double *ToBeMoved;
if(level >= PROCESS) { /* yintrpt case */
scr_rowcol(0, 0);/* move cursor to upper left, a routine in
desmet's pcio.a */
}
else
PRINT "\n");
erase_line();
PRINT
"Hit digit or letter of vector whose coordinates will change(Use 0 for y[])\n"
);
acceptable = ChooseStorageVec(0);
/* Character == 0 means StorVec is not provided
*/
Sto = StorChar;
if(acceptable == 1) {
if(level >= PROCESS) {/* yintrpt case */
scr_rowcol(0, 0);
/* move cursor to upper left, a routine in
desmet's pcio.a */
erase_line();
PRINT "\n");
erase_line();
PRINT "\n");
erase_line();
scr_rowcol(1, 0);
}
else
PRINT "\n");
ToBeMoved = ystore_in;/* pointers */
if(input == StInput) {
erase_line();
PRINT "y%c. Fine. \n", StorChar);
PRINT
"Now hit the digit or letter for vec whose coordinates will be copied to y%c\n"
,StorChar);
}
acceptable = ChooseStorageVec(0);
if(acceptable == YES) {
store(ToBeMoved, ystore_in, eqn1);
if(level >= PROCESS) {/* yintrpt case */
scr_rowcol(0, 0);
/* move cursor to upper left, a routine in
desmet's pcio.a */
erase_line();
PRINT "\n");
erase_line();
PRINT "\n");
erase_line();
PRINT "\n");
erase_line();
scr_rowcol(1, 0);
}
PRINT "\n");
if(input == StInput)
PRINT
" y%c[] has been copied to y%c[] \n\n", StorChar, Sto);
ystore_in = ToBeMoved;
return;
}
}
PRINT "Not acceptable; start over to try again \n");
}
null() {
} /* dummy */
print_text(output) /* for sending output of data to file output;
in particular it can go to printer LPT1
which is done by calling
print_text(StPrint); at least this works
with IBMPCs; the amount of data printed
depends on "printer" or to the screen */
FILE * output;
{
double x,
X,
yval,
Y;
if(printer > 0)
if(fprintf(output, " ") == -1) {/* check for error */
printf(
"The program cannot access the output file. Perhaps the printer is off \n");
return;
}
if(bifTextFlag == OFF) /* i.e. not using command BIF */
if(printer == 1) {
if(rho != -9999.)
fprintf(output, "rho = %15.10lf ", rho);
if(output == StOutPut)
fprintf(output, "Last dot was %ld. ", dot);
fprintf(output, "\n");
}
if(printer > 1) {
if(bifTextFlag == OFF)/* i.e. not using command BIF */
if(picNameFlag == YES)
/* means DiskFileName has been accessed, either
storing or reading */
fprintf(output,
"Associated Disk file name: \"%s\" \n", DiskFileName);
map_menu(output, MapName);
if(bifTextFlag == OFF)/* i.e. not using command BIF */
if(rho != -9999.)
fprintf(output, "rho = %lf ", rho);
if(step != -9999)
fprintf(output, "step = %lf\n", step);
if(C1 != -9999)
fprintf(output, "C1 = %lf ", C1);
if(C2 != -9999)
fprintf(output, "C2 = %lf ", C2);
if(C3 != -9999)
fprintf(output, "C3 = %lf ", C3);
if(C4 != -9999)
fprintf(output, "C4 = %lf ", C4);
if(C5 != -9999)
fprintf(output, "C5 = %lf ", C5);
if(C6 != -9999)
fprintf(output, "C6 = %lf ", C6);
if(C7 != -9999)
fprintf(output, "C7 = %lf ", C7);
if(C8 != -9999.)
fprintf(output, "C8 = %lf ", C8);
if(beta != -9999.)
fprintf(output, " beta = %lf ;", beta);
if(sigma != -9999.)
fprintf(output, " sigma = %lf ;", sigma);
fprintf(output, "\n");
x = X_Lo[ScrnSec];
X = X_Up[ScrnSec];
yval = Y_Lo[ScrnSec];
Y = Y_Up[ScrnSec];
if(ScrnSec != 0)
fprintf(output, "Section F%d X coord: from %lf to %lf; "
,ScrnSec, x, X);
else
fprintf(output, "X coord: from %lf to %lf; ", x, X);
if(bifTextFlag == OFF)/* i.e. not using command BIF */
fprintf(output, "Y coord: %lf to %lf\n", yval, Y);
if(preiter != 0)
fprintf(output, "preiterates before plotting = %ld\n"
,preiter);
if(bifTextFlag == OFF)/* i.e. not using command BIF */
fprintf(output, "Last dot was %ld. ", dot);
if(bifTextFlag == OFF)/* i.e. not using command BIF */
if(dim > 2 || X_coord != 0 || Y_coord != 1)
fprintf(output,
"Coordinate numbers(0 to %d) are: %d and %d"
,dim - 1, X_coord, Y_coord);
fprintf(output, "\n");
if(lyaptime > 0.&& num_lyap > 0)
print_lyap(output);
if(output != StOutPut)
fprintf(output, "\n\n");
} /* end > 1 case */
}
print_y() { /* used with newton method, called from
YCASES2.C */
int ii;
for(ii = 0; ii < lyapzero; ii++) {
erase_line();
PRINT "y[%d] = %15.12lf \n", ii, y[ii]);
}
if(vec_dim == 2 && lyapzero > 2) {
erase_line();
PRINT
" The phase space variables are y[%d] and y[%d]\n"
,zeroth, zeroth + 1);
}
}
int random997 () { /* Returns an integer between 0 and 997 using
external frac */
double rdm;
int R;
rdm = 997 * frac;
R = rdm;
frac = rdm - R;
return(R);
}
euler() { /* this Euler routine is for a single step of
the differential equation; DE is a pointer
to a function */
int i;
double k[EQTNS0];
(*DE) (k, y);
for(i = 0; i < dim; i++)
y[i] += step * k[i];
t = t + step;
}
ret_erase_line(i) /* gives i copies of return(plus line feed) +
erase_line() */
int i;
{
int n;
for(n = 0; n < i; n++) {
PRINT "\n");
erase_line();
}
}
rungekutta() { /* this fourth order Runge_Kutta routine is for
a single step of the differential equation;
DE is a pointer to a function */
int i;
double k1[EQTNS0],
k2[EQTNS0],
k3[EQTNS0],
k4[EQTNS0];
double temp[EQTNS0];
(*DE) (k1, y);
for(i = 0; i < dim; i++)
temp[i] = y[i] + halfstep * k1[i];
(*DE) (k2, temp);
for(i = 0; i < dim; i++)
temp[i] = y[i] + halfstep * k2[i];
(*DE) (k3, temp);
for(i = 0; i < dim; i++)
temp[i] = y[i] + step * k3[i];
(*DE) (k4, temp);
for(i = 0; i < dim; i++)
y[i] += sixth_step * (k1[i] + 2.* k2[i] + 2.* k3[i] + k4[i]);
t = t + step;
}
int ScanfForCoefs(A, B, pVec)
/* the coordinates acceptable are >= A and < B;
the routine asks for a coordinate first; if
it is acceptable, it asks for a double
precision value to plug into the
corresponding coordinate; if successful, and
coord < B-1, a 1 is returned so inputting
can continue; otherwise 0 is returned; if
the routine is not successful in getting
both a coordinate and a double, pVec is not
changed */
int A,
B;
double *pVec;
{
int coord,
i;
double DOUB;
int ret;
if(input == StInput)
for(i = A; i < B; i++)
PRINT "coordinate %d = %10.10lf \n", i, pVec[i]);
if(input == StInput)
puts("To change a coordinate, input coordinate number and RETURN\n");
if(input == StInput)
puts("To LEAVE values UNCHANGED, just hit RETURN\n");
coord = -1;
DOUB = -19999.;
ret = 0;
#ifdef X11
if(input == StInput && sscanf(xwfgets(), "%d", &coord) != 1
|| input != StInput && fscanf(input, "%d", &coord) != 1)
return(0);
#else
if (SCREEN && abortEnter() == YES || fscanf(input," %d",&coord) != 1)
return(0);
#endif
if(coord < B && coord >= A) {
if(input == StInput)
PRINT
"Enter new value of coordinate # %d, then RETURN\n", coord);
#ifdef X11
if(input == StInput && sscanf(xwfgets(), "%lf", &DOUB) != 1
|| input != StInput && fscanf(input, "%lf", &DOUB) != 1)
return(0);
#else
if(SCREEN && abortEnter() == YES ||
fscanf(input, "%lf", &DOUB) != 1)
return(0);
#endif
if(DOUB != -19999) {
pVec[coord] = DOUB;
ret = 1;/* means coordinate was satisfactorily entered
*/
if(coord == B - 1)
ret = 0;/* B-1 = last coord */
}
}
else if(coord != -1)
puts("Illegal coordinate. Not accepted. \n");
if(ret == 0)
if(input == StInput)
for(i = A; i < B; i++)
PRINT "coordinate %d = %lf\n", i, pVec[i]);
return(ret);
}
setequal(J, K, dimen)
int J,
K,
dimen;
{
int i,
j,
k;
if(J == 0)
j = 0;
else
j = eqn0 + eqn1 * (J - 1);
if(K == 0)
k = 0;
else
k = eqn0 + eqn1 * (K - 1);
for(i = 0; i < dimen; i++)
y[j + i] = y[k + i];
}
store(yp0, yp1, dimen) /* yp0 and yp1 are pointers; the vector starting
at yp1 is stored in the vector beginning at
yp0; dimen is the number of coordinates to be
transfered */
double *yp0,
*yp1;
int dimen;
{
int i;
for(i = 0; i < dimen; i++)
yp0[i] = yp1[i];
}
y_init_init() { /* this routine sets the initalization vector;
it is used before the default parameters of
a map or differential equation are set;
hence other values can be set when the
defaults are set */
int i,
k;
for(i = 0; i < eqn1; i++) {
y[eqn0 + i] = 0.;
for(k = 2; k < NUM_Y; k++)
y[eqn0 + (k - 1) * eqn1 + i] = -9999.;
}
y[eqn0 + 1] = 1.;
}
double Fn3 () { /* this is designed for the Lorenz system; the
pair of stationary solutions that the
solution oscillates around has z(= y[2]) =
rho - 1 */
return(y[2] - rho + 1);
}
double FnLinY() {
int J;
double F;
F = 0;
for(J = 0; J < dim; J++)
F = F + PoincareCoef[J] * y[J];
return(F);
}
/* insert and test later
double FnDeriv()... this is a linear function of the derivative with the
same coefficients as FnLinY()
{
int J;
double F;
double k1[EQTNS0];
(*DE)(k1,y);
F = 0;
for(J = 0; J < dim; J++)
F = F + PoincareCoef[J]*y[J];
return(F);
}
*/
SetPoincareCoefs() {
int J;
if(input == StInput)
PRINT
"set Poincare cross section coeficients for J >= 0, J < %d; currently \n", dim);
if(input == StInput)
for(J = 0; J < dim; J++)
PRINT
" PoincareCoef[%d] = %lf; \n", J, PoincareCoef[J]);
while(ScanfForCoefs(0, dim, PoincareCoef)) {;
}
return;
}
#ifndef UNIX
pause(sec) /* pause for this number of seconds */
double sec; /* we use sleep() on Unix systems */
{
int timevector[4];
double timeofday(), time0;
time0 = timeofday(timevector);
while(timeofday(timevector) - time0 < sec);
return;
}
#endif /* UNIX */